﻿
using System;
using System.Drawing;

using GECS.Core;
using GECS.Object;

namespace GECS.MapEngine {

	/// <summary>
	/// Implements the view of the map so that a map can scroll indefinitely. The
	/// offsets are calculated automatically when the static method Follow() is
	/// called by the object in it's respective Update() method.
	/// </summary>
    public class MapView {

		/// <summary>
		/// The x-Offset.
		/// </summary>
        public static int OffSetX = 0;
        /// <summary>
        /// The y-Offset.
        /// </summary>
        public static int OffSetY = 0;

        private static Rectangle vrect = new Rectangle(0, 0, Global.WIDTH, Global.HEIGHT);

        /// <summary>
        /// Calculates the offset values so that an object will be centered in the
        /// view. Instead of rendering the map, use the MapView's render method so
        /// that only the visible portion of the map is drawn.
        /// </summary>
        /// <param name="obj">The object which is to be centered.</param>
        public static void Follow(GObject obj) {
            OffSetX = OffSetY = 0;
            if (Map.Width > Global.WIDTH) {
            	OffSetX = (int)Math.Round(Global.WIDTH/2 - obj.X - Map.TILE_SIZE);
                OffSetX = Math.Min(OffSetX, 0);
                OffSetX = Math.Max(OffSetX, Global.WIDTH - Map.Width);
            }
            if (Map.Height > Global.HEIGHT) {
            	OffSetY = (int)Math.Round(Global.HEIGHT/2 - obj.Y - Map.TILE_SIZE);
                OffSetY = Math.Min(OffSetY, 0);
                OffSetY = Math.Max(OffSetY, Global.HEIGHT - Map.Height);
            }
        }

        /// <summary>
        /// Returns a rectangle which is the visible portion of the game. Note that
        /// the offset values are not included in the objects.
        /// </summary>
        public static Rectangle VisibleRect {
            get {
                return vrect;
            }
        }

        /// <summary>
        /// Render's the map with this view. Only the visible objects and tiles are rendered.
        /// </summary>
        /// <param name="g">The graphics context.</param>
        public static void Render(Graphics g) {
            Map.RenderMap(g, OffSetX, OffSetY);
        }

        /// <summary>
        /// Checks if an object is visible or not according to the view.
        /// </summary>
        /// <param name="obj">The object to be checked.</param>
        /// <returns>True if visible, else false.</returns>
        public static bool IsVisible(GObject obj) {
            int x1 = 0;
            int y1 = 0;
            int x2 = (int) obj.X + OffSetX;
            int y2 = (int) obj.Y + OffSetY;
            if (x1 < x2 + obj.Width) {
                if (x2 < x1 + Global.WIDTH) {
                    if (y1 < y2 + obj.Height) {
                        if (y2 < y1 + Global.HEIGHT) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }
        
        /// <summary>
        /// Checks if a tile is visible or not according to the view.
        /// </summary>
        /// <param name="t">The tile to be checked.</param>
        /// <returns>True if visible, else false.</returns>
        public static bool IsVisible(Tile t) {
            int x1 = 0;
            int y1 = 0;
            int x2 = (int) t.X + OffSetX;
            int y2 = (int) t.Y + OffSetY;
            if (x1 < x2 + t.Width) {
                if (x2 < x1 + Global.WIDTH) {
                    if (y1 < y2 + t.Height) {
                        if (y2 < y1 + Global.HEIGHT) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

    }

}
